/*
 * 版权所有 © 2025，Amor。保留所有权利。
 * 在MIT许可证条款下发布。
 * 
 * 功能：
 * 1. 本文件实现了LoongArch64架构的缓存控制功能
 * 2. 提供了以下主要功能：
 *    - 清除数据缓存 (arch_clean_cache_range)
 *    - 使数据缓存失效 (arch_invalidate_cache_range) 
 *    - 清除并使数据缓存失效 (arch_clean_invalidate_cache_range)
 *    - 使指令缓存失效 (arch_invalidate_icache_range)
 *    - 启用/禁用缓存控制 (arch_cache_enable/disable)
 * 3. 所有缓存操作都通过LoongArch64的CACOP指令实现
 * 4. 本实现针对EFI启动环境进行了优化
 * 
 * 注意：
 * 1. 本文件仅适用于LoongArch64架构
 * 2. 本文件仅适用于EFI启动环境
 * 
 * 
 * 作者: Amor, 2025年4月
 */

#include <boot/platform.h>
#include <boot/stage2.h>
#include <boot/stdio.h>
#include <kernel.h>

#include <arch_cpu_defs.h>

// LoongArch64缓存操作指令
#define CACHE_OP_D_INVAL			0x01
#define CACHE_OP_D_WB				0x02
#define CACHE_OP_D_WB_INVAL		0x03
#define CACHE_OP_I_INVAL			0x11

// 缓存操作辅助函数
static inline void
cache_op(unsigned int op, void* addr, size_t size)
{
	size_t i;
	for (i = 0; i < size; i += 4) {
		asm volatile("cacop %0, %1, 0" : : "i"(op), "r"((unsigned long)addr + i));
	}
	// 确保缓存操作完成
	asm volatile("dbar 0" : : : "memory");
}

// 清除数据缓存
void
arch_clean_cache_range(addr_t start, size_t size)
{
	cache_op(CACHE_OP_D_WB, (void*)start, size);
}

// 使数据缓存失效
void
arch_invalidate_cache_range(addr_t start, size_t size)
{
	cache_op(CACHE_OP_D_INVAL, (void*)start, size);
}

// 清除并使数据缓存失效
void
arch_clean_invalidate_cache_range(addr_t start, size_t size)
{
	cache_op(CACHE_OP_D_WB_INVAL, (void*)start, size);
}

// 使指令缓存失效
void
arch_invalidate_icache_range(addr_t start, size_t size)
{
	cache_op(CACHE_OP_I_INVAL, (void*)start, size);
}

// 启用缓存
void
arch_cache_enable()
{
	// LoongArch64在启动时已经启用了缓存
	// 这里不需要额外操作
}

// 禁用缓存
void
arch_cache_disable()
{
	// 在引导阶段，我们通常不会禁用缓存
	// 这里不执行任何操作
}